#include "IniFileParser.h"

// 私有成员函数，用于读取INI文件并填充iniMap
bool IniFileParser::parseIniFile(const std::string &filename)
{
    std::ifstream file(filename);
    if (!file.is_open())
    {
        std::cerr << "Unable to open file: " << filename << std::endl;
        return false;
    }

    std::string line;
    while (std::getline(file, line))
    {
        // 跳过空行
        if (line.empty())
        {
            continue;
        }

        // 查找#字符的位置
        size_t commentPos = line.find('#');

        // 如果找到了#字符，则只保留#之前的部分（包括#前的空格，但不包括#本身）
        if (commentPos != std::string::npos)
        {
            line = line.substr(0, commentPos);
        }

        // 跳过完全由空白字符组成的行（此时line可能已被截断为仅包含空白）
        size_t startPos = line.find_first_not_of(" \t");
        if (startPos == std::string::npos)
        {
            continue;
        }
        size_t pos = line.find(':');
        if (pos != std::string::npos)
        {
            std::string key = line.substr(0, pos);
            std::string value = line.substr(pos + 1);
            // 去除key和value两端的空白字符
            key.erase(0, key.find_first_not_of(" \t"));
            key.erase(key.find_last_not_of(" \t\r\n") + 1);
            value.erase(0, value.find_first_not_of(" \t"));
            value.erase(value.find_last_not_of(" \t\r\n") + 1);

            // 将键值对存储到map中
            iniMap[key] = value;
        }
    }

    file.close();
    return true;
}

// 构造函数可以自动尝试解析INI文件
IniFileParser::IniFileParser(const std::string &filename)
{
    if (!parseIniFile(filename))
    {
        throw std::runtime_error("Failed to parse INI file");
    }
}

// 尝试获取指定键的值，如果键不存在则返回空字符串
bool IniFileParser::getStrValue(const std::string &key, std::string &value) const
{
    auto it = iniMap.find(key);
    if (it != iniMap.end())
    {
        value = it->second;
        return true;
    }
    std::cerr << "Key not found in INI file: " << key << std::endl;
    return false;
}

// 尝试将指定键的值转换为整型，如果转换失败或键不存在则抛出异常
bool IniFileParser::getIntValue(const std::string &key, int &value) const
{
    auto it = iniMap.find(key);
    if (it != iniMap.end())
    {
        try
        {
            value = std::stoi(it->second);
            return true;
        }
        catch (const std::invalid_argument &e)
        {
            throw std::runtime_error("Invalid integer value for key: " + key);
        }
        catch (const std::out_of_range &e)
        {
            throw std::runtime_error("Integer value out of range for key: " + key);
        }
    }
    std::cerr << "Key not found in INI file: " << key << std::endl;
    return false;
}

// int main() {
//     try {
//         IniFileParser parser("config.ini");

//         // 尝试获取并打印IP地址（作为字符串）
//         std::string ip = parser.getValue("ip");
//         std::cout << "IP Address: " << ip << std::endl;

//         // 尝试获取并打印端口号（作为整型）
//         int port = parser.getIntValue("port");
//         std::cout << "Port Number: " << port << std::endl;
//     } catch (const std::exception& e) {
//         std::cerr << "Error: " << e.what() << std::endl;
//     }

//     return 0;
// }